home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / utility / 533 / kwic / kwic.pas < prev    next >
Pascal/Delphi Source File  |  1991-07-02  |  21KB  |  598 lines

  1.  
  2. {$D+,R+,P+,C+,U10}                      {Compiled via command line}
  3.  
  4.  {Project #359. Key words in context.}
  5. PROGRAM KWIC;
  6. {$I GEMSUBS.PAS}
  7. {$I AUXSUBS.PAS}
  8. {$I CURRENT\KWIC.I}
  9.  
  10. (*
  11.                   Program    : Key Words in Context
  12.                   Version    : 1.0
  13.                   Language   : Personal Pascal 2.05
  14.                   Resource   : K-Resource by Kuma
  15.                   Written by : Merlin L. Hanson
  16.                   Date       : July 1991
  17.  
  18.                          *** Pseudocode ***
  19. Read the input data file
  20. Read the file of words to be excluded
  21. for all lines do
  22.   remember where each line starts
  23.   for all words do
  24.     if word is not in the exclusion list, add the word to outlist
  25. sort the list
  26. print the entries
  27. Note: outlist is a 2-tuple: word, line number in the file.
  28.       exclusion list is a list of the articles, prepositions, and any 
  29.       ad-hoc words the user wishes to add.  
  30.       For speed, put the 'bad words' into a linked list with the bases
  31.       in an array corresponding to 'a'..'z'.
  32.                             *** end ***                of pseudocode   *)      
  33.                             
  34. (*CONST            actual declaration is in file KWIC.I *)
  35.  
  36.   VAR
  37.     Printer : {FILE OF}text;  
  38.     RSC_Name : path_name;
  39.  
  40. {             *** Subprograms of a utility nature are listed ***
  41.                      prior to the main procedure (DoIt)          }
  42.                      
  43.  
  44. PROCEDURE Abort(s:string);
  45.   BEGIN{abort}
  46.     WriteLn(s);
  47.     WriteLn('Press return');
  48.     ReadLn;
  49.     HALT;
  50.   END{abort};
  51.  
  52. {Returns TRUE if there is a character in the keyboard buffer.
  53. Follow with ReadLn (not Read) to 'eat' the character.}
  54. FUNCTION KeyPressed:boolean;
  55.   GEMDOS($0B);  {aka CONSTAT, aka cconis}
  56.   
  57. {If any key has been pressed, wait for press of [Return].
  58. Then return control to the caller.  Unfortunately, the key pressed
  59. will be displayed on the monitor.}
  60. PROCEDURE Pause;
  61.   BEGIN {pause}
  62.     IF KeyPressed
  63.       THEN ReadLn;
  64.   END{pause};    
  65.   
  66. {Empty the keyboard buffer so that user and the program are in synch
  67. with each other.}
  68. PROCEDURE DrainKbd;
  69.   BEGIN
  70.     WHILE KeyPressed DO
  71.       ReadLn;                           {To that big bit-bucket in the sky.}
  72.   END{drainkbd};
  73.  
  74. {                    *** Get File Name ***
  75. Display 'Note' above the file selector box.  Display 'Current' drive
  76. and path for path name. Display 's' as suggested file name.
  77. Return 's' as a full drive/path/file name.}
  78. PROCEDURE GetFileName(Note:string;  VAR s:path_name);
  79.   VAR MyPath:path_name;  x_coord:integer;    
  80.     
  81.   PROCEDURE GetDriveAndPath(VAR S:string);
  82.     { A procedure that returns a Pascal string containing the current drive,
  83.     current path and all punctuation.  Simply append a raw file name.}
  84.     VAR
  85.       i : integer;
  86.       T : string;
  87.       Path : string;
  88.       DriveString : string;
  89.  
  90.     FUNCTION CurrentDisk:integer;
  91.       {Returns an integer specifying the current drive. 0 specifies A, etc.}
  92.       GEMDOS($19);
  93.  
  94.     PROCEDURE GetDir(VAR Ptr:string; DriveID:integer);
  95.       {Puts a C string defining the folders currently open on DriveID
  96.       into S.  DriveID of 0 specifies the current drive.}
  97.       GEMDOS($47);
  98.  
  99.     BEGIN {getdriveandpath}
  100.       DriveString := CONCAT(CHR(ORD('A')+CurrentDisk),':');
  101.       GetDir(Path,0);
  102.       {Convert from C to Pascal.}
  103.       i := 0;
  104.       WHILE Path[i] <> CHR(0) DO
  105.         BEGIN
  106.           T[i+1] := Path[i];
  107.           i := i+1;
  108.         END;
  109.       {Set the length}
  110.       T[0] := CHR(i);
  111.       S := CONCAT(DriveString,T,'\');
  112.     END {getdriveandpath};
  113.   
  114.   BEGIN{getfilename}
  115.     x_coord := 40 - (LENGTH(Note) DIV 2);
  116.     GOTOXY(x_coord,1);
  117.     Write(#27,'p');           {invert color}
  118.     Write(Note);
  119.     Write(#27,'q');           {normal color}
  120.     GetDriveAndPath(MyPath);
  121.     IF GET_IN_FILE(MyPath,s)
  122.       THEN {  }
  123.       ELSE HALT;
  124.   END{getfilename};
  125.  
  126. {Returns the lower case equivalent of an upper case character.}
  127. FUNCTION LowerCase(ch:char):char;
  128.   BEGIN
  129.     IF (ch >= 'A') AND (ch <= 'Z')
  130.       THEN LowerCase := CHR(ORD(ch)+32)
  131.       ELSE LowerCase := ch;
  132.   END {lowercase};
  133.   
  134. PROCEDURE DoDither;
  135.   VAR w,h:integer;
  136.   FUNCTION GetRez:integer;
  137.     XBIOS(4);
  138.   BEGIN{dodither}
  139.     Hide_Mouse;
  140.     CASE GetRez OF
  141.       0 : BEGIN w := 320; h := 200; END;
  142.       1 : BEGIN w := 640; h := 200; END;
  143.       2 : BEGIN w := 640; h := 400; END;
  144.     END{case};  
  145.     Paint_Style(5);
  146.     Paint_Rect(0,0,w,h);
  147.     Show_Mouse;
  148.   END{dodither};
  149.     
  150.                          (**************************
  151.                          *** Principal Procedure ***
  152.                          **************************)
  153. PROCEDURE DoIt;            (******************)  
  154.   TYPE 
  155.     s254 = string[254];
  156.     s11  = string[11];                      {max length of a key word}
  157.     T158 = integer;                         {because the sort was a 'stock' item and was paramaterized}
  158.     T383 = s11;
  159.     T857 = PACKED ARRAY[1..110000]OF char;  {max size of input file}
  160.     T062 = 1..8000;                         {max number of key words}
  161.     T141 = ARRAY[T062] OF s11;
  162.                {*** Following used by procedure ReadBad ***}
  163.     T269 = ^T838;
  164.     T838 = RECORD
  165.              KeyWd : s11;                {Word to be ignored} 
  166.              Link  : T269;
  167.            END{record};
  168.     T560 = ARRAY[0..25] OF T269;         {for a,b,c, .. ,z}    
  169.   VAR
  170.     Arr  : T857;                         {Character array copy of text file.}
  171.     inix : long_integer;                 {always index for 'Arr'}
  172.     NbrBytes  : long_integer;            {number of bytes in the input file}    
  173.     Leftmost  : integer;                 {key words are left justified to this column.}
  174.     i,LineNbr : integer;
  175.     Letter : SET OF char;
  176.     junk : char;
  177.     junki : integer;
  178.     {The next 2 should properly be a single record, but the sort routine
  179.     (pre-built) sorts arrays of a rather simple kind; 
  180.     not arrays of records.  The index is simply the order of acquisiton
  181.     of the word from the original text file.}
  182.     KeyWdArr : {ARRAY[T062] OF s11}  T141;  {list of key words.}
  183.     TheLine  :  ARRAY[T062] OF integer;     {line nbr associated 
  184.                                             with the key word.}
  185.     NextIx   : integer;                     {index for above 2}                                        
  186.                 (*** end of 'parallel' variables ***)
  187.     FirstCh  :  ARRAY[1..3600] OF long_integer;  
  188.                                  {FirstCh[j] contains the 
  189.                                  inix value of the first char of line j.
  190.                                  The input file can have up to 3600 lines.}
  191.     NextFirst : integer;         {allocation index for FirstCh.}           
  192.     LastKStrt : integer;         {ignore words starting after this column.}
  193.     fnstr     : path_name;       {file name string}
  194.     {              *** used by bad word logic *** }
  195.     BadBase : {ARRAY [0..25] OF ^record}  T560;
  196.  
  197.   {$I MLIBPAS\TXTTOARR.PAS}
  198.  
  199.   {Read all the bad words into one of 26 linked lists.  This provides 
  200.   a 'good enough for government work' sort to speed things up.}
  201.   PROCEDURE ReadBad;       (*****************)
  202.     VAR
  203.       BadFile : text;
  204.       Str     : s11;
  205.       i       : integer;
  206.       s2      : string;
  207.     
  208.     {Append S to the appropriate list.}
  209.     PROCEDURE AddStr(S:s11);
  210.       VAR ix:0..25;   Temp:T269;  Ptr:T269;
  211.       BEGIN {addstr}
  212.         ix := ORD(S[1]) - 97;  {'a' becomes 0}
  213.         NEW(Ptr);
  214.         Ptr^.Link := NIL;
  215.         Ptr^.KeyWd := s;
  216.         {Assert: Ptr points at the new entry.  Now add the new entry
  217.         to the linked list.}
  218.         Temp := BadBase[ix];
  219.         IF BadBase[ix] = NIL
  220.           THEN BadBase[ix] := Ptr  {add to root}
  221.           ELSE                     {add at end of list}
  222.             BEGIN
  223.               Temp := BadBase[ix];
  224.               WHILE Temp^.link <> NIL DO
  225.                 Temp := Temp^.link;
  226.               {Temp points at the last viable entry.}  
  227.               Temp^.link := Ptr;
  228.             END;  
  229.       END{addstr};
  230.     
  231.     {Print all the 'b's in the list.}   (* for test *)
  232.     PROCEDURE PrintList;
  233.       VAR Temp:T269;
  234.       BEGIN{printlist}
  235.         Temp := BadBase[1];
  236.         WHILE Temp <> NIL DO
  237.           BEGIN
  238.             WriteLn(Temp^.KeyWd);
  239.             Temp := Temp^.link;
  240.           END;  
  241.       END{printlist};
  242.     
  243.     BEGIN{readbad}
  244.       FOR i := 0 TO 25 DO
  245.         BadBase[i] := NIL;
  246.       fnstr := 'BADWDS.TXT';
  247.       GetFileName(' Choose words to be excluded ',fnstr);
  248.       RESET(BadFile,fnstr);  
  249.       WHILE NOT EOF(BadFile) DO
  250.         BEGIN
  251.           ReadLn(BadFile,str);
  252.           AddStr(str);
  253.         END;
  254.     END{readbad};
  255.   
  256.   PROCEDURE GetLength(VAR FinalCol:integer);
  257.     VAR junk,Choice:integer; ThisBox:dialog_ptr; S:string[255];
  258.     BEGIN
  259.       Choice := DO_ALERT(
  260.         '[0][Ignore rightmost columns|        of input?][ Yes | No ]'   ,2);
  261.       IF Choice = 1
  262.         THEN 
  263.           BEGIN
  264.             Find_Dialog(LgthBox,ThisBox);
  265.             Center_Dialog(ThisBox);
  266.             junk := Do_Dialog(ThisBox,0);
  267.             Get_DEdit(ThisBox,LastCol,S);
  268.             READV(s,FinalCol);
  269.             FinalCol := FinalCol + 1;   {fudge}
  270.           END
  271.         ELSE FinalCol := 999;  
  272.     END{getlength};
  273.     
  274.   PROCEDURE MakeList;      (*****************)
  275.     VAR Wd:s11; Done,Bummer:boolean; Line:integer; StartIx,StartLine:long_integer;
  276.   
  277.     FUNCTION FindStr(s:string):boolean;
  278.       VAR Find:boolean; Temp:T269;  i,ix:integer;
  279.       BEGIN{findstr}
  280.         FOR i := 1 TO LENGTH(s) DO
  281.           s[i] := LowerCase(s[i]);
  282.         ix := ORD(s[1]) - 97;
  283.         Temp := BadBase[ix];
  284.         Find := FALSE;
  285.         WHILE (Temp <> NIL) AND (NOT Find) DO
  286.           IF Temp^.KeyWd = S
  287.             THEN Find := TRUE
  288.             ELSE Temp := Temp^.link;
  289.         FindStr := Find;    
  290.       END{findstr};
  291.  
  292.     PROCEDURE GetWord(VAR str:s11; VAR LineNumber:integer);  
  293.       VAR Done : boolean; 
  294.  
  295.       PROCEDURE SaveFirst(ix:long_integer);
  296.         BEGIN
  297.           FirstCh[NextFirst] := ix;
  298.           NextFirst := NextFirst + 1;
  299.           StartLine := inix;
  300.         END{savefirst};  
  301.  
  302.       {Append characters to the string until the end of the word is found.}      
  303.       PROCEDURE FindEnd;
  304.         BEGIN{findend}
  305.           WHILE NOT Done DO 
  306.             IF Arr[inix] IN Letter
  307.               THEN BEGIN
  308.                 (*Personal Pascal has a flaw in the CONCAT logic.
  309.                 It won't detect a string overflow here so logic added
  310.                 to do so.*)
  311.                 IF LENGTH(str) < 11
  312.                   THEN str := CONCAT(str,Arr[inix]);
  313.                 inix := inix + 1;
  314.               END  
  315.             ELSE IF Arr[inix] = #13
  316.               THEN BEGIN
  317.                 LineNbr := LineNbr + 1;
  318.                 Done := True;
  319.                 inix := inix + 2;
  320.                 SaveFirst(inix);
  321.               END  
  322.             ELSE BEGIN {blank, comma, ...}
  323.                 Done := TRUE;
  324.                 inix := inix + 1;
  325.               END;  
  326.         END{findend};
  327.         
  328.       {Find the firat character of a word.  Then pass control to
  329.       'FindEnd' to locate the last character of that word.}
  330.       BEGIN{getword}
  331.         {Find the first character and put it in the string.}
  332.         str := '';
  333.         LineNumber := LineNbr;  {LineNbr may be advanced before return to here!}
  334.         StartIx := inix;
  335.         Done := FALSE;
  336.         REPEAT
  337.         IF (Arr[inix] IN Letter) AND (inix < NbrBytes)
  338.         AND ((inix - StartLine) < LastKStrt)
  339.           THEN 
  340.             BEGIN
  341.               {First char in a word}
  342.               str := CONCAT(str,Arr[inix]);
  343.               inix := inix + 1;
  344.               FindEnd;
  345.             END
  346.           ELSE IF Arr[inix] = ' '
  347.             THEN  inix := inix + 1
  348.           ELSE IF Arr[inix] = #13
  349.             THEN 
  350.               BEGIN
  351.                 LineNbr := LineNbr + 1;
  352.                 Done := TRUE;
  353.                 inix := inix + 2;
  354.                 SaveFirst(inix);
  355.               END
  356.           ELSE 
  357.             {Garbage character of some sort.}
  358.             inix := inix + 1;  
  359.           UNTIL Done;
  360.       END{getword};
  361.       
  362.     BEGIN{makelist}
  363.       Done := FALSE;
  364.       Letter := ['a'..'z','A'..'Z','0'..'9','''','-'];
  365.       StartLine := inix;
  366.       WHILE inix < NbrBytes DO
  367.         BEGIN
  368.           GetWord(Wd,Line);
  369.           IF (Wd[1] IN ['a'..'z','A'..'Z']) AND (LENGTH(Wd) > 0)
  370.             THEN Bummer := FindStr(Wd);
  371.           IF NOT Bummer AND (LENGTH(Wd) > 0)
  372.             THEN 
  373.               BEGIN
  374.                 KeyWdArr[NextIx] := Wd;       {The key word just found}
  375.                 TheLine[NextIx]  := Line;     {Line number in original text}
  376.                 NextIx := NextIx + 1;
  377.               END;  
  378.         END;  
  379.         {Assert: NextIx - 1 key words were retained.}
  380.         WriteLn('list done');
  381.     END{makelist};
  382.  
  383.   {$I MLIBPAS\QUCKSRT2.PAS}
  384.  
  385.   {Get, from the user, the leftmost column that key words will be aligned to.}  
  386.   PROCEDURE GetJustify(VAR n:integer);  
  387.     VAR junk:integer;  s:string[255];  ThisBox:dialog_ptr;
  388.     BEGIN
  389.       Find_Dialog(LeftBox,ThisBox);
  390.       Center_Dialog(ThisBox);
  391.       junk := Do_Dialog(ThisBox,0);
  392.       Get_DEdit(ThisBox,LftCol,S);
  393.       READV(s,n);
  394.     END{getjustify};
  395.  
  396.   PROCEDURE DoOutput(LeftJustify:integer);  (******************)
  397.     VAR junk:integer; ThisBox:dialog_ptr;  MyStr:string; Choice:tree_index;
  398.     
  399.     PROCEDURE UserDialog;
  400.       VAR Width,junk:integer;
  401.       BEGIN
  402.         DoDither;
  403.         Choice := Do_Alert(
  404.         '[0][Epson compatible printer?][ No | Yes ]',2);
  405.         IF Choice = 2 
  406.           THEN
  407.             BEGIN
  408.               Write(Printer,#27,'@',#07);   {Reset the printer, sound the bell.}
  409.               Width := DO_ALERT(
  410.                 '[0][         Print width?         ][ 80 col | 137 col ]'  ,1  );
  411.               DoDither;  
  412.               IF Width = 2
  413.                 THEN Write(Printer,#15);    {compressed mode on an Epson printer.}  
  414.               Write(Printer,#27,'N',#6);    { Skip 6 lines at perforations.}  
  415.             END;    
  416.         DoDither;    
  417.         junk := DO_Alert(
  418.           '[0][Is the paper aligned?][ OK ]'  ,1);
  419.       END{userdialog};
  420.   
  421.     {Print the lines defined in array 'TheLine'.}  
  422.     PROCEDURE PrintList;
  423.       LABEL 100;
  424.       VAR ThisLine : integer;
  425.     
  426.       {Print the line specified by the parameter.}
  427.       PROCEDURE PrintLine(LineNbr:integer;  KeyWd:string);
  428.         VAR s:s254; chix:long_integer;  Offset,i:integer;
  429.         BEGIN
  430.           s := '';
  431.           chix := FirstCh[LineNbr];
  432.           REPEAT
  433.             IF LENGTH(S) < 253
  434.               THEN S := CONCAT(S,Arr[chix]);
  435.             chix := chix + 1;  
  436.           UNTIL Arr[chix - 1] = #10;  {line feed}
  437.           {Assert: S is the line to print.  Align so KeyWd starts at
  438.           column 'LeftJustify'.}
  439.           Offset := POS(KeyWd,S);
  440.           {If Offset is >= LeftJustify, the DO will not execute and the datum will
  441.           be left justified to column 1.}  
  442.           FOR i := 1 TO LeftJustify - Offset DO
  443.             Write(' ');
  444.           Write(s);  
  445.         END{printline};
  446.       
  447.       BEGIN{printlist}
  448.         {Assert: 'TheLine' is a sorted list of lines in the original file to
  449.         print.  The same line number can appear several times in the 
  450.         array, once for each key word to be printed.}
  451.         FOR ThisLine := 1 TO NextIx-1 DO
  452.           BEGIN
  453.             IF NOT KeyPressed 
  454.               THEN PrintLine(TheLine[ThisLine],KeyWdArr[ThisLine])
  455.               ELSE 
  456.                 BEGIN
  457.                   junk := DO_ALERT('[0][Outpt aborted][ OK ]',1);
  458.                   GOTO 100;
  459.                 END;
  460.           END{do loop};  
  461. 100:        
  462.       END{printlist};
  463.       
  464.     BEGIN{dooutput}    
  465.       Find_Dialog(OutBox,ThisBox);
  466.       Center_Dialog(ThisBox);
  467.       Choice := Do_Dialog(ThisBox,0);
  468.       DrainKbd;
  469.       CASE Choice OF  {B stands for button}
  470.         BMonitor : BEGIN
  471.                      (*Write(#27,'E');    {clear screen}*)
  472.                      DoDither;
  473.                      junk := 
  474.    DO_ALERT('[0][Use Control S and Control Q|     to suspend monitor][ OK ]',1);
  475.                      REWRITE(OUTPUT,'CON:');
  476.                      HIDE_MOUSE;
  477.                      Write(#27,'E');    {Clear the screen.}
  478.                      DrainKbd;
  479.                      PrintList;  
  480.                      Write('... Press return');
  481.                      ReadLn;
  482.                      DoDither;
  483.                      SHOW_MOUSE;
  484.                    END;  
  485.         BFile    : BEGIN
  486.                      MyStr := 'KWIC.OUT';
  487.                      GetFileName(' Choose output file ',MyStr);
  488.                      REWRITE(OUTPUT,MyStr);
  489.                      PrintList;
  490.                      CLOSE(OUTPUT);
  491.                    END{file write};  
  492.         BPrntr   : BEGIN
  493.                      UserDialog;
  494.                      REWRITE(OUTPUT,'PRN:');
  495.                      PrintList; 
  496.                    END;  
  497.         BExit    : HALT;  {Normal exit for program.}
  498.       END {case};  
  499.       OBJ_SETSTATE(ThisBox,Choice,Normal,TRUE);
  500.     END{dooutput};
  501.     
  502.   BEGIN{doit}                     (*******************)
  503.     junki := DO_ALERT(
  504. '[0][Key Words in Context|     Version 1.0| by Merlin L. Hanson][ OK ]',1) ;
  505.     fnstr := 'KWICINPT.TXT';
  506.     GetFileName('Choose Input File',fnstr);
  507.     ReadFile(fnstr,Arr,NbrBytes,FALSE);
  508.     inix := 1;                          {'point at' the first character}
  509.     ReadBad;
  510.     DoDither;                           {Erase .PRG produced file prompts}
  511.     GetLength(LastKStrt);
  512.     FirstCh[1] := 1;   
  513.     NextFirst := 2;
  514.     LineNbr := 1;
  515.     NextIx := 1;
  516.     Write(#27,'E',#10);                  {Clear screen, line feed.}
  517.     WriteLn('Computing...');
  518.     WriteLn('Make a list');
  519.     MakeList;
  520.     WriteLn('Number KWIC entries:',nextix-1);
  521.     {Assert: A 2-tuple has been created for each key word.
  522.        KeyWdArr contains a list of the key words  (The same key word can recur many times.)
  523.        TheLine  contains the line number in the original text
  524.     Also:   
  525.        FirstCh  is the offset in 'Arr' of the _first_ character of each _line_
  526.                 in the input file.
  527.                 Note that a sort is _not_ wanted on FirstCh.}
  528.     WriteLn('Start sort  ', NextIx-1,' items');  
  529.     QuickSort(KeyWdArr,NextIx-1);
  530.     WriteLn('Sort done');  
  531.     GetJustify(Leftmost);
  532.     REPEAT
  533.       DoDither;
  534.       DoOutput(Leftmost);   {contains an end of program exit}
  535.     UNTIL FALSE;  
  536.   END{doit};
  537.     
  538. BEGIN {program}
  539.   REWRITE(Printer,'PRN:');
  540.   RSC_Name := 'KWIC.RSC';
  541.   IF INIT_GEM >= 0
  542.     THEN 
  543.       IF LOAD_RESOURCE(RSC_Name)
  544.         THEN 
  545.           BEGIN
  546.             DoIt;
  547.             EXIT_GEM;
  548.           END  
  549.         ELSE Abort('Can''t find .RSC file');
  550. END{program}.
  551.  
  552.                         (*** OVERALL STRUCTURE ***
  553.                         Line numbers are approximate
  554.     7 PROGRAM KWIC;
  555.     8 {$I GEMSUBS.PAS}
  556.     9 {$I AUXSUBS.PAS}
  557.    10 {$I CURRENT\KWIC.I}
  558.    41 PROCEDURE Abort(s:string);
  559.    51 FUNCTION KeyPressed:boolean;
  560.    57 PROCEDURE Pause;
  561.    65 PROCEDURE DrainKbd;
  562.    75 PROCEDURE GetFileName(Note:string;  VAR s:path_name);
  563.    78  |PROCEDURE GetDriveAndPath(VAR S:string);
  564.    87  | |FUNCTION CurrentDisk:integer;
  565.    91  | |PROCEDURE GetDir(VAR Ptr:string; DriveID:integer);
  566.    96  | |BEGIN {getdriveandpath}
  567.   111  |BEGIN{getfilename}
  568.   124 FUNCTION LowerCase(ch:char):char;
  569.   131 PROCEDURE DoDither;
  570.   133  |FUNCTION GetRez:integer;
  571.   135  |BEGIN{dodither}
  572.   148 PROCEDURE DoIt;            (******************)  
  573.   192  {$I MLIBPAS\TXTTOARR.PAS}
  574.   196  |PROCEDURE ReadBad;       (*****************)
  575.   204  | |PROCEDURE AddStr(S:s11);
  576.   227  | |PROCEDURE PrintList;
  577.   238  | |BEGIN{readbad}
  578.   251  |PROCEDURE GetLength(VAR FinalCol:integer);
  579.   269  |PROCEDURE MakeList;      (*****************)
  580.   272  | |FUNCTION FindStr(s:string):boolean;
  581.   274  | | |BEGIN{findstr}
  582.   287  | |PROCEDURE GetWord(VAR str:s11; VAR LineNumber:integer);  
  583.   290  | | |PROCEDURE SaveFirst(ix:long_integer);
  584.   298  | | |PROCEDURE FindEnd;
  585.   299  | | | |BEGIN{findend}
  586.   325  | | |BEGIN{getword}
  587.   357  | |BEGIN{makelist}
  588.   378  |{$I MLIBPAS\QUCKSRT2.PAS}
  589.   381  |PROCEDURE GetJustify(VAR n:integer);  
  590.   391  |PROCEDURE DoOutput(LeftJustify:integer);  (******************)
  591.   394  | |PROCEDURE UserDialog;
  592.   417  | |PROCEDURE PrintList;
  593.   422  | | |PROCEDURE PrintLine(LineNbr:integer;  KeyWd:string);
  594.   442  | | |BEGIN{printlist}
  595.   459  | |BEGIN{dooutput}  
  596.   496  |BEGIN{doit}              (****************) 
  597.   532 BEGIN {program}    *)                        
  598.